import functools
import json
import random
import string
import time

import requests

from app import db
from application.tools.comm import sendMsg
from captcha.image import ImageCaptcha
from flask import Blueprint, request, send_file, jsonify, redirect
from application.models.users.user import *
from application.tools.myjwt import mjwt
from application.tools.myredis import r

# 权限认证
def islogin(func):
    @functools.wraps(func)
    def wrapper():
        # 设置一个白名单，白名单是一个列表，列表里面有的数据就不需要进行token验证，如果没有就进行验证是否存在token
        whitelist = ['/user/getcode', '/user/sendSmsCode', '/user/login']
        # 获取前端访问的url
        url = request.path
        print('url================================', url)
        # 判断访问的接口是否存在白名单
        if url not in whitelist:
            # 从接口headers中获取token
            try:
                token = request.headers.get('token')
                print('token================================', token)
                # 调用封装好的jwt进行对比
                flag = mjwt.check_token(token)
                if flag == True:
                    # 如果通过就验证token是否过期
                    # 调用封装好的jwt进行解密
                    payload = mjwt.jwt_decode(token)
                    # 获取现在的时间
                    now = time.time()
                    # 获取token存入的有效期
                    tnow = payload['data']['exp']
                    # 判断token是否过期
                    if int(now)-int(tnow) > 3:
                        # 如果过期就返回用户登录信息过期

                        return jsonify({'code': '203', 'msg': '用户登录信息已过期'})
                else:
                    return jsonify({'code': '202', 'msg': 'token已经篡改'})
            except:
                return jsonify({'code': '201', 'msg': 'token不存在'})
        func()
        return func
    return wrapper



user_blue = Blueprint("userblue", __name__)
from application.tools.comm import get_ali_object
@user_blue.route("/text")
def text():
    orderno = '234234'
    pay = get_ali_object()
        # 生成支付的url
    query_params = pay.direct_pay(
        subject="test",  # 商品简单描述
        out_trade_no=str(orderno),  # 用户购买的商品订单号（每次不一样） 20180301073422891
        total_amount=float(100.00),  # 交易金额(单位: 元 保留俩位小数)
    )
    pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
    return jsonify({"code":200,'url':pay_url})
# 获取图形验证码
@islogin
@user_blue.route("/getcode", methods=["GET"])
def getcode():
    img_code = "".join(random.sample(string.digits+string.ascii_letters, 4)) # 随机获取字符串+数字的的4个字符
    cap = ImageCaptcha() # 生成图形验证码
    img = cap.generate(img_code) # 使用生成图片
    # 从页面中获取uuid作为redis key
    uuid = str(request.args.get("uuid"))
    # 写入redis
    r.str_add(uuid, str(img_code), 60)

    return send_file(img, 'image/png')


# 发送短信验证码
@islogin
@user_blue.route('/sendSmsCode', methods=['POST'])
def sendSmsCode():
    data = request.data
    # 校验前端传来的参数
    if data:
        data = json.loads(data)
        # 获取3个参数
        mobile = data.get("mobile")
        img_code = data.get("piccode")
        uuid = data.get("uuid")
        print("img_code=======================", img_code, uuid, mobile)
        # 通过uuid查询
        value = r.str_get(uuid)
        print("value=======================", value)
        # 判断图形验证码是否存在
        if value:
            # 校验短信验证码
            if value.lower() == img_code.lower():
                # 验证短信验证码一分钟只能发送一次
                sms_code = r.str_get(mobile)
                # 判断手机号是否一分钟发送验证码
                if sms_code:
                    return jsonify({"code": 10013, "msg": "一分钟之内不能重复发送"})
                # 生成短信验证码
                scode = random.randint(000000, 999999)
                # 调用短信发送平台
                flag = sendMsg(mobile, scode)
                if flag == True:
                    # 将短信存入存入redis数据库中
                    print('scode: %s' % scode)
                    r.str_add(mobile, scode, 60)
                    a = r.str_get(mobile)
                    print("a==========:", a)
                    # 删除图形验证码
                    r.str_del(uuid)
                    # 返回结果
                    return jsonify({"code": 200, "msg": "发送成功"})
                else:
                    return jsonify({"code": 10001, "msg": "发送失败"})
            return jsonify({"code": 10012, "msg": "图形验证码错误"})

        else:
            return jsonify({"code": 10011, "msg": "图形验证码不存在"})
        # 校验图形验证码是否正确
    else:
        return jsonify({"code": 10010, "msg": "参数错误"})






# 注册和登录接口
@islogin
@user_blue.route("/login", methods=["POST"])
def login():
    # 接收前端参数
    data = request.data
    # 校验前端参数
    if data:
        data = json.loads(data)
        # 获取 手机号，验证码
        mobile = data.get("mobile")
        code = data.get("code")
        print('code======mobile', code, mobile)
        # 查询出redis数据库存储的验证码
        mcode = r.str_get(mobile)
        print('mcode======', mcode)
        # 校验验证码是否存在
        if mcode:
            # 校验短信验证码是否正确
            if code == mcode:
                # 查询手机号是否存在
                user = User.query.filter(User.mobile == mobile).first()
                # 判断是否获取过来数据
                if user:
                    # 删除redis中存储的短信验证码
                    r.str_del(mobile)
                # 如果不存在，就进行添加该用户
                else:
                    u = User(mobile=mobile, nikename=mobile)
                    db.session.add(u)
                    db.session.commit()
                    user = User.query.filter(User.mobile == mobile, User.nikename == mobile).first()
                # 用户信息生成token
                token = mjwt.jwt_encode(data={"data": {'uid': user.id, 'exp': int(time.time())}})
                # 返回信息给页面
                return jsonify({'code': 10000, 'token': token, 'userid': user.id})

            # 返回短信验证码错误
            else:
                return jsonify({"code": 10003, 'msg': '短信验证码错误'})
        # 如果验证码不存在返回结果
        else:
            return jsonify({"code": 10001, "meg": "短信验证码不存在"})
    # 返回参数错误
    return jsonify({"code": 10002, 'meg': "请输入，正确的数据"})


# 获取weibo地址
@user_blue.route("/getwburl")
def  getwburl():
    client_id = "3674019597"
    redirect_uri = "http://127.0.0.1:8000/user/weiboCallback/"
    url = "https://api.weibo.com/oauth2/authorize?clien t_id=%s&response_type=code&redirect_uri=%s" % (client_id, redirect_uri)
    return jsonify({"code": 200, "url": url})

# weibo回调接口
@user_blue.route("/weiboCallback/",)
def weiboCallback():
    # 获取code
    mes = request.args
    # code = request.args.get('code')
    # # 向access_token接口发起post请求
    # data = {"client_id": '3674019597', "client_secret": "7ae99bc0d54ead29fc8d1b9fabd78587",
    #         "grant_type": "authorization_code",
    #         'redirect_uri': 'http://127.0.0.1:8000/user/weiboCallback/', 'code': code}
    # res = requests.post('https://api.weibo.com/oauth2/access_token', data=data)
    # mes = json.loads(res.text)
    # 解析参数，token，uid
    token = mes['access_token']
    uid = mes['uid']
    # 查询三方登录中uid是否存在，如果存在，查询用户表，用用户信息生成token跳转到vue页面
    sql = "select user.id from user inner join sf_login on user.id=sf_login.userid where sf_login.uid='%s'"%(uid)
    user = db.session.execute(sql)
    print(user)
    if user:
        for i in user:
            data = {'data': {'userid': i[0], 'exp': int(time.time())}}
            token = mjwt.jwt_encode(data)
            print("没返回222222")
            return redirect('http://localhost:8080/#/updateToken?userid='+i[0]+"&token="+token)
    # 不存在跳转到vue绑定页面， token， uid传递过去
    print("没返回11111")
    return redirect('http://localhost:8080/#/bindMobile?'+uid+"&token="+token)
# 绑定手机号
@user_blue.route("/bindMobile", methods=['POST'])
def bindMObile():
    data = json.loads(request.data)
    mobile = data.get('mobile')
    uid = data.get('uid')
    token = data.get('token')
    # 先查询用户表， 如果手机号存在
    user = User.query.filter(User.mobile == mobile).first()
    print(user)
    if user == None:
        print('22')
        u = User(mobile=mobile, nikename=mobile)
        db.session.add(u)
        db.session.commit()
        # 获取用户信息
        user = User.filter(User.mobile == mobile).first()
        print(user)
    #
    sfuser = SfLogin(userid=user.id, webfrom='wb', uid=uid, token=token)
    db.session.add(sfuser)
    db.session.commit()
    # 如果不存在， 写入user表
    # 获取userid 写入三方登录表， 生成token返回
    data = {'data': {'userid': user.id, 'exp': int(time.time())}}
    token = mjwt.jwt_encode(data)
    return jsonify({'userid': str(user.id), token: token})

@user_blue.route('/buy',methods=['POST'])
def buy():
    # 获取参数
    data = json.loads(request.data)
    userid = data['userid']
    year = data['year']
    money = 200
    tmoney = money * int(year)
    # 生成订单号
    order_no = str(int(time.time()))+str(userid)+str(random.randint(100,999))
    # 写入VIP记录表
    viprecord = VipRecord(order_no=order_no,userid=userid,year=year,money=tmoney,active_money=tmoney,status=1)
    db.session.add(viprecord)
    db.session.commit()
    # 支付，返回支付url
    pay = get_ali_object()
        # 生成支付的url
    query_params = pay.direct_pay(
        subject="test",  # 商品简单描述
        out_trade_no=str(order_no),  # 用户购买的商品订单号（每次不一样） 20180301073422891
        total_amount=float(100.00),  # 交易金额(单位: 元 保留俩位小数)
    )
    pay_url = "https://openapi.alipaydev.com/gateway.do?{0}".format(query_params)  # 支付宝网关地址（沙箱应用）
    return jsonify({"code":200,'url':pay_url})
import datetime
@user_blue.route('callback')
def callback():
    #接收参数
    data = request.args
    datames = {k:v for k,v in data.items()}
    #删除字典中key为sign 的记录
    sign = datames.pop('sign')
    #鉴权  订单号  流水号
    pay = get_ali_object()
    flag = pay.verify(datames ,sign)

    if flag == True:
        #订单号
        transaction_no = datames ['trade_no']
        #支付宝流水号
        order_no = datames['out_trade_no']
        # 事务处理
        # try:
            #订单号更新订单表
        record = VipRecord.query.filter(VipRecord.order_no == order_no).first()
        record.status = 2
        record.transaction_no=transaction_no
        db.session.add(record)
        #更新用户表
        User.query.filter(User.id == record.userid).update({'level':2})
        #更新vip表
        vip = Vip.query.filter(Vip.userid == record.userid,Vip.status==1).first()
        if vip is not None:
            #结束时间+购买年限
            # etime = vip.e_time.split("-")
            # tyear = int(etime[0]) + int(record.year)
            # yearstr = '-'
            # etime[0] = str(tyear)
            # retime = yearstr.join(etime)
            year = 365 * int(record.year)
            retime = vip.e_time + datetime.timedelta(days=year)
            vip.e_time = retime
            db.session.add(vip)
        else:
            year = 365 * int(record.year)
            retime = datetime.datetime.now()+datetime.timedelta(days=year)
            # nowyear = datetime.date.strftime(datetime.datetime.now(),"%Y-%m-%d %H:%m:%s")
            # etime = nowyear.split("-")
            # tyear = int(etime[0]) + int(record.year)
            # etime[0] = str(tyear)
            # yearstr = '-'
            # retime = yearstr.join(etime)
            vip = Vip(userid=record.userid,s_time=datetime.datetime.now(),e_time=retime)
            db.session.add(vip)
        db.session.commit()
        # except:
        #     db.session.rollback()
    else:
        print('鉴权失败')
    return 'ok'



    # data = request.args
    # dict = {k:v for k,v in data.items()}
    #
    # sign = dict.pop('sign')
    #
    # pay = get_ali_object()
    # flag = pay.verify(dict,sign)
    # print(flag)
    # return 'ok'

# 添加课程使用， 获取标签，分类， 类别
@user_blue.route("/getTags")
def getTags():
    tags = Tags.query.all()
    tagslist = [{'id':i.id,'name':i.name} for i in tags]
    types = Ctype.query.all()
    typeslist = [{'id':i.id,'name':i.name} for i in types]
    ctype = CourseType.query.all()
    clist = [{'id':i.id,'name':i.name} for i in ctype]
    return jsonify({"code":200,"tags":tagslist,'types':typeslist,'clist':clist})

from qiniu import Auth
@user_blue.route("/get_qntoken")
def get_qntoken():
    # -*- coding: utf-8 -*-
    # flake8: noqa
    from qiniu import Auth
    # 需要填写你的 Access Key 和 Secret Key
    access_key = 'PreRDw06bAO6l1rp3jYQ14emYXPu4YAz-kXxc7Im'
    secret_key = 'ImiyB_v7CH-QJgnc5cNbjRMCjx_mvm_dAtwEO0OM'
    # 构建鉴权对象
    q = Auth(access_key, secret_key)
    # 要上传的空间
    bucket_name = 'h2205a-ljy'
    # 3600为token过期时间，秒为单位。3600等于一小时
    token = q.upload_token(bucket_name)
    return jsonify({"code": 200, "token": token})

@user_blue.route("/addCourse",methods=['POST'])
def addCourse():
    # try:
    # 获取参数
    data = json.loads(request.data)
    # 写入课程表
    course = Course(name=data['name'],url=data['url'],descrip=data['desc'],ctype=data['type'])
    db.session.add(course)
    # 获取新添加的课程id
    scourse = Course.query.filter(Course.name == data['name']).first()
    # 写入课程标签表
    for i in data["tags"]:
        sql = 'insert into course_tag(courseid,tagid) values(%d,%d)'%(scourse.id,int(i))
        db.session.execute(sql)
    # 课程分类表
    for i in data["ctype"]:
        sql = 'insert into course_cate(courseid,course_typeid) values(%d,%d)'%(scourse.id,int(i))
        db.session.execute(sql)
    db.session.commit()
    return jsonify({"code": 200})
    # except:
    #     db.session.rollback()
    # return jsonify({"code":400,"mes":'添加失败'})

import math
@user_blue.route("/getCourse")
def getCourse():
    # 获取参数page
    page = int(request.args.get("page"))
    # 获取上线即将上线条件

    # 获取上线，即将上线条件
    online = int(request.args.get("is_publish"))
    # 查询总条数
    total = Course.query.filter(Course.is_publish==online).count()
    # 定义每页显示多少条
    page_size=2
    # 查询当前页面记录
    start = math.ceil((page-1)*page_size)
    #获取排序字段
    orderpara = request.args.get("orderpara")
    if orderpara == 'new':
        course = Course.query.order_by(Course.create_time.desc()).filter(Course.is_publish == online).offset(start).limit(page_size).all()
    else:
        course = Course.query.order_by(Course.views.desc()).filter(Course.is_publish == online).offset(start).limit(page_size).all()

    list = [{"id":i.id,"name":i.name,'url':i.url,"views":i.views} for i in course]
    # 返回结果
    return jsonify({"code":200,"clist":list,"total":total,"page_size":page_size})




@user_blue.route("/cart", methods=["POST"])
def cart():
    pass






